### version and initialization
define([ENTROPY_VER_MAJ],[0])
define([ENTROPY_VER_MIN],[9.1])
define([ENTROPY_BUILD],[439])

AC_INIT([entropy], ENTROPY_VER_MAJ[.]ENTROPY_VER_MIN[-]ENTROPY_BUILD)

# Caching is off by default in Autoconf >= 2.50.  Offer a suggestion.
if test "$cache_file" = "/dev/null"; then
	AC_MSG_NOTICE([])
	AC_MSG_NOTICE(["configure" caching is disabled!])
	AC_MSG_NOTICE([consider using "./configure -C" to make rebuilds faster])
	AC_MSG_NOTICE([])
fi

AC_CANONICAL_TARGET

case $target in
*-*-interix*)
	CPPFLAGS="-D_ALL_SOURCE $CPPFLAGS";;
esac

### libraries
AC_SEARCH_LIBS(socket, [socket])

### headers
AC_STDC_HEADERS

AC_CHECK_HEADERS([sys/ipc.h], [
	AC_CHECK_HEADERS([sys/shm.h],,,[#include <sys/ipc.h>])
])

### sizes
AC_CHECK_SIZEOF(unsigned char)
AC_CHECK_SIZEOF(unsigned short)
AC_CHECK_SIZEOF(unsigned int)
AC_CHECK_SIZEOF(unsigned long)
AC_CHECK_SIZEOF(unsigned long long)

### types
AC_CHECK_TYPES([socklen_t],,,[
#include <sys/types.h>
#include <sys/socket.h>
])

### compiler characteristics
AC_C_BIGENDIAN
AC_C_INLINE

### library functions
AC_CHECK_FUNCS([flock futimes getpagesize mmap strtoull timegm utimes])

AC_ARG_ENABLE([setproctitle], AC_HELP_STRING([--enable-setproctitle], [display per-process information in "ps"]))
if test "${enable_setproctitle:-no}" != "no"; then
	AC_CHECK_FUNCS([setproctitle])
fi

### declarations
AC_CHECK_DECLS([sys_signame, _sys_signame],,, [#include <signal.h>])

### compile and runtime options
AC_ARG_ENABLE([debug], AC_HELP_STRING([--disable-debug], [disable debugging output]))
if test "${enable_debug:-yes}" != "no"; then
	AC_DEFINE(DEBUG, 1, [Define to 1 to enable debugging output.])
fi

AC_ARG_ENABLE([verbose], AC_HELP_STRING([--enable-verbose], [enable verbose build messages]))
AC_SUBST(VERBOSE, [${enable_verbose:-no}])

AC_ARG_ENABLE([warnings], AC_HELP_STRING([--disable-warnings], [disable extra compiler warnings]))
if test "${enable_warnings:-yes}" != "no"; then
	CFLAGS="$CFLAGS -W -Wall -Wuninitialized"
fi
CFLAGS="$CFLAGS -Wno-unused"

### choose datastore type
AC_ARG_WITH([mysql], AC_HELP_STRING([--with-mysql(=path)], [use MySQL data store (MySQL is installed at path)]), [
	if test -n "$withval"; then
		if test -d "$withval/include/mysql"; then
			CPPFLAGS="$CPPFLAGS -I$withval/include/mysql"
		else
			CPPFLAGS="$CPPFLAGS -I$withval/include"
		fi
		if test -d "$withval/lib/mysql"; then
			LDFLAGS="$LDFLAGS -L$withval/lib/mysql"
		else
			LDFLAGS="$LDFLAGS -L$withval/lib"
		fi
	fi

	AC_CHECK_HEADER(mysql.h,, [AC_MSG_ERROR([C compiler can't find <mysql.h>])])
	AC_SEARCH_LIBS(mysql_real_connect, mysqlclient,, [AC_MSG_ERROR([C compiler can't find mysqlclient library functions])])
	AC_MSG_NOTICE([MySQL datastore selected])
	STORE_TYPE=2
], [
	AC_ARG_WITH([tree], AC_HELP_STRING([--with-tree], [use directory tree data store]), [
		AC_MSG_NOTICE([Tree datastore selected])
		STORE_TYPE=1
	], [
		AC_MSG_NOTICE([Monolithic datastore selected])
		STORE_TYPE=0
	])
])

AC_DEFINE_UNQUOTED(STORE_TYPE, $STORE_TYPE, [Define to 1 for a directory tree store, 2 for MySQL store.])
AC_SUBST(STORE_TYPE)

### choose semaphore type (need to detect datastore first)
have_mi_sems=false

if ! $have_mi_sems; then
	AC_ARG_ENABLE([flock-sem], AC_HELP_STRING([--disable-flock-sem], [do not attempt to use flock semaphores]))
	if test "${enable_flock_sem:-yes}" != "no"; then
		AC_CHECK_HEADERS([sys/fcntl.h], [
			AC_MSG_CHECKING([whether to use flock semaphores])
			AC_MSG_RESULT([yes])
			AC_DEFINE(USE_FLOCK_SEMAPHORES, 1, [Define to 1 to use flock semaphores.])
			have_mi_sems=true
		],, [#include <sys/fcntl.h>])
	fi
fi

if ! $have_mi_sems; then
	AC_ARG_ENABLE([posix-sem], AC_HELP_STRING([--disable-posix-sem], [do not attempt to use POSIX unnamed semaphores]))
	if test "${enable_posix_sem:-yes}" != "no"; then
		AC_CHECK_HEADERS([semaphore.h], [
			AC_SEARCH_LIBS(sem_init, [posix4 pthread], [
				AC_MSG_CHECKING([whether to use POSIX unnamed semaphores])
				AC_RUN_IFELSE([
AC_LANG_PROGRAM([#include <semaphore.h>], [
	sem_t mysem;
	if (0 == sem_init(&mysem, 1, 1)) {
		if (0 == sem_wait(&mysem)) {
			sem_post(&mysem);
			sem_destroy(&mysem);
			return 0;
		}
	}
	return 1;
])
				], [
					AC_MSG_RESULT([yes])
					AC_DEFINE(USE_POSIX_SEMAPHORES, 1, [Define to 1 to use POSIX unnamed semaphores.])
					have_mi_sems=true
				], [
					AC_MSG_RESULT([no (pshared not usable)])
				], [
					AC_MSG_RESULT([no (cannot check usability when cross-compiling)])
				])
			])
		])
	fi
fi

# XXX disable SVID sems by default on linux until cause of EINVAL is found - tv
# (this can still be enabled with --enable-svid-sem)
case $target in
*-*-linux*)
	: ${enable_svid_sem:=no}
	;;
esac

if ! $have_mi_sems; then
	AC_ARG_ENABLE([svid-sem], AC_HELP_STRING([--disable-svid-sem], [do not attempt to use SysV semaphores]))
	if test "${enable_svid_sem:-yes}" != "no"; then
		AC_CHECK_HEADERS([sys/sem.h], [
			AC_SEARCH_LIBS(semget, [ipc], [
				AC_MSG_CHECKING([whether to use SVID IPC semaphores])
				AC_MSG_RESULT([yes])
				AC_DEFINE(USE_SVID_SEMAPHORES, 1, [Define to 1 to use SVID IPC semaphores.])
				have_mi_sems=true
			])
		],, [#include <sys/ipc.h>])
	fi
fi

if ! $have_mi_sems; then
	AC_MSG_CHECKING([whether to use userspace assembly semaphores])
	case $target in
	i?86-*-*)
		AC_DEFINE(X86, 1, [Define if on an x86-type processor.])
		;;
	x86_64-*-*)
		AC_DEFINE(X86, 1, [Define if on an x86-type processor.])
		;;

	powerpc-*-*)
		AC_DEFINE(PPC, 1, [Define if on a PowerPC-type processor.])
		;;

	*)
		AC_MSG_RESULT([no])
		AC_MSG_ERROR([no working semaphores available for $target])
		;;
	esac
	AC_MSG_RESULT([yes])
fi

### enable target-specific compiler options
AC_SUBST(COPYLIBS)

case $target in
i?86-*-*)
	AC_DEFINE(X86, 1, [Define if on an x86-type processor.])
	;;
x86_64-*-*)
	AC_DEFINE(X86, 1, [Define if on an x86-type processor.])
	;;
*-apple-darwin*)
	# -prebind on Darwin/Mac OS X
	# (temporarily disabled at request of Rescue  -tv)
	#CFLAGS="-prebind $CFLAGS"
	;;
esac

case $target in
powerpc-*-*)
	AC_ARG_ENABLE([ppc-g5], AC_HELP_STRING([--enable-ppc-g5],[enable PowerPC G5 optimizations]))
	if test "${enable_ppc_g5:-no}" != "no"; then
		CFLAGS="$CFLAGS -mcpu=970 -mtune=970 -mpowerpc64"
	fi
	;;
esac

### set code version constants
AC_DEFINE(NODE_VER_MAJ, "ENTROPY_VER_MAJ", [Major version of Entropy.])
AC_DEFINE(NODE_VER_MIN, "ENTROPY_VER_MIN", [Minor protocol level version of Entropy.])
AC_DEFINE(NODE_BUILD, "ENTROPY_BUILD", [Build level of Entropy.])

AC_SUBST(NODE_VER_MAJ, ENTROPY_VER_MAJ)
AC_SUBST(NODE_VER_MIN, ENTROPY_VER_MIN)
AC_SUBST(NODE_BUILD, ENTROPY_BUILD)

### output files
AC_CONFIG_HEADERS([include/config.h])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

### config.h top and bottom
AH_TOP([
#ifndef	_CONFIG_H_
#define	_CONFIG_H_
])

AH_BOTTOM([
/* -*- c -*- */

#ifdef STDC_HEADERS
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_MEMORY_H
#include <memory.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif /* HAVE_MEMORY_H */
#endif /* HAVE_STRING_H */

#if 1	/* no HAVE_xxx_H for these? */
#include <time.h>
#include <sys/time.h>
#endif

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif

/* Hello DOS-world! */
#ifndef	O_BINARY
#define	O_BINARY	0
#endif

#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#else
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#if SIZEOF_UNSIGNED_LONG_LONG==8
typedef unsigned long long uint64_t;
typedef long long int64_t;
#elif SIZEOF_UNSIGNED_LONG==8
typedef unsigned long uint64_t;
typedef long int64_t;
#else
#error I do not know what to use for a uint64_t.
#endif
/* Give us an unsigned 32-bit data type. */
#if SIZEOF_UNSIGNED_LONG==4
typedef unsigned long uint32_t;
typedef long int32_t;
#elif SIZEOF_UNSIGNED_INT==4
typedef unsigned int uint32_t;
typedef int int32_t;
#else
#error I do not know what to use for a uint32_t.
#endif
/* Give us an unsigned 16-bit data type. */
#if SIZEOF_UNSIGNED_INT==2
typedef unsigned int uint16_t;
typedef int int16_t;
#elif SIZEOF_UNSIGNED_SHORT==2
typedef unsigned short uint16_t;
typedef short int16_t;
#else
#error I do not know what to use for a uint16_t.
#endif
/* Give us an unsigned 8-bit data type */
#if SIZEOF_UNSIGNED_CHAR==1
typedef unsigned char uint8_t;
#else
#error I do not know what to use for a uint8_t.
#endif
#endif	/* HAVE_STDINT_H */
#endif	/* HAVE_INTTYPES_H */

/* Define machine endianess */
#ifndef	BYTE_ORDER
#ifndef	LITTLE_ENDIAN
#define	LITTLE_ENDIAN	4321
#endif
#ifndef	BIG_ENDIAN
#define	BIG_ENDIAN	1234
#endif
#ifdef	WORDS_BIGENDIAN
#define	BYTE_ORDER BIG_ENDIAN
#else
#define	BYTE_ORDER LITTLE_ENDIAN
#endif
#endif

#endif /* !defined(_CONFIG_H_) */
])
